{
 "cells": [
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.527156Z",
     "start_time": "2025-02-28T15:08:23.523859Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.datasets import load_iris\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.datasets import load_iris\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from matplotlib.colors import ListedColormap\n",
    "from sklearn.model_selection import train_test_split"
   ],
   "id": "5ad7628823d027db",
   "outputs": [],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.539146Z",
     "start_time": "2025-02-28T15:08:23.534743Z"
    }
   },
   "cell_type": "code",
   "source": [
    "lis = load_iris()\n",
    "print(lis.keys())"
   ],
   "id": "5e4a1ed570e7adb5",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.546525Z",
     "start_time": "2025-02-28T15:08:23.540679Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(lis.feature_names)\n",
    "print(lis.data)"
   ],
   "id": "8d8c9b8eb53546ed",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']\n",
      "[[5.1 3.5 1.4 0.2]\n",
      " [4.9 3.  1.4 0.2]\n",
      " [4.7 3.2 1.3 0.2]\n",
      " [4.6 3.1 1.5 0.2]\n",
      " [5.  3.6 1.4 0.2]\n",
      " [5.4 3.9 1.7 0.4]\n",
      " [4.6 3.4 1.4 0.3]\n",
      " [5.  3.4 1.5 0.2]\n",
      " [4.4 2.9 1.4 0.2]\n",
      " [4.9 3.1 1.5 0.1]\n",
      " [5.4 3.7 1.5 0.2]\n",
      " [4.8 3.4 1.6 0.2]\n",
      " [4.8 3.  1.4 0.1]\n",
      " [4.3 3.  1.1 0.1]\n",
      " [5.8 4.  1.2 0.2]\n",
      " [5.7 4.4 1.5 0.4]\n",
      " [5.4 3.9 1.3 0.4]\n",
      " [5.1 3.5 1.4 0.3]\n",
      " [5.7 3.8 1.7 0.3]\n",
      " [5.1 3.8 1.5 0.3]\n",
      " [5.4 3.4 1.7 0.2]\n",
      " [5.1 3.7 1.5 0.4]\n",
      " [4.6 3.6 1.  0.2]\n",
      " [5.1 3.3 1.7 0.5]\n",
      " [4.8 3.4 1.9 0.2]\n",
      " [5.  3.  1.6 0.2]\n",
      " [5.  3.4 1.6 0.4]\n",
      " [5.2 3.5 1.5 0.2]\n",
      " [5.2 3.4 1.4 0.2]\n",
      " [4.7 3.2 1.6 0.2]\n",
      " [4.8 3.1 1.6 0.2]\n",
      " [5.4 3.4 1.5 0.4]\n",
      " [5.2 4.1 1.5 0.1]\n",
      " [5.5 4.2 1.4 0.2]\n",
      " [4.9 3.1 1.5 0.2]\n",
      " [5.  3.2 1.2 0.2]\n",
      " [5.5 3.5 1.3 0.2]\n",
      " [4.9 3.6 1.4 0.1]\n",
      " [4.4 3.  1.3 0.2]\n",
      " [5.1 3.4 1.5 0.2]\n",
      " [5.  3.5 1.3 0.3]\n",
      " [4.5 2.3 1.3 0.3]\n",
      " [4.4 3.2 1.3 0.2]\n",
      " [5.  3.5 1.6 0.6]\n",
      " [5.1 3.8 1.9 0.4]\n",
      " [4.8 3.  1.4 0.3]\n",
      " [5.1 3.8 1.6 0.2]\n",
      " [4.6 3.2 1.4 0.2]\n",
      " [5.3 3.7 1.5 0.2]\n",
      " [5.  3.3 1.4 0.2]\n",
      " [7.  3.2 4.7 1.4]\n",
      " [6.4 3.2 4.5 1.5]\n",
      " [6.9 3.1 4.9 1.5]\n",
      " [5.5 2.3 4.  1.3]\n",
      " [6.5 2.8 4.6 1.5]\n",
      " [5.7 2.8 4.5 1.3]\n",
      " [6.3 3.3 4.7 1.6]\n",
      " [4.9 2.4 3.3 1. ]\n",
      " [6.6 2.9 4.6 1.3]\n",
      " [5.2 2.7 3.9 1.4]\n",
      " [5.  2.  3.5 1. ]\n",
      " [5.9 3.  4.2 1.5]\n",
      " [6.  2.2 4.  1. ]\n",
      " [6.1 2.9 4.7 1.4]\n",
      " [5.6 2.9 3.6 1.3]\n",
      " [6.7 3.1 4.4 1.4]\n",
      " [5.6 3.  4.5 1.5]\n",
      " [5.8 2.7 4.1 1. ]\n",
      " [6.2 2.2 4.5 1.5]\n",
      " [5.6 2.5 3.9 1.1]\n",
      " [5.9 3.2 4.8 1.8]\n",
      " [6.1 2.8 4.  1.3]\n",
      " [6.3 2.5 4.9 1.5]\n",
      " [6.1 2.8 4.7 1.2]\n",
      " [6.4 2.9 4.3 1.3]\n",
      " [6.6 3.  4.4 1.4]\n",
      " [6.8 2.8 4.8 1.4]\n",
      " [6.7 3.  5.  1.7]\n",
      " [6.  2.9 4.5 1.5]\n",
      " [5.7 2.6 3.5 1. ]\n",
      " [5.5 2.4 3.8 1.1]\n",
      " [5.5 2.4 3.7 1. ]\n",
      " [5.8 2.7 3.9 1.2]\n",
      " [6.  2.7 5.1 1.6]\n",
      " [5.4 3.  4.5 1.5]\n",
      " [6.  3.4 4.5 1.6]\n",
      " [6.7 3.1 4.7 1.5]\n",
      " [6.3 2.3 4.4 1.3]\n",
      " [5.6 3.  4.1 1.3]\n",
      " [5.5 2.5 4.  1.3]\n",
      " [5.5 2.6 4.4 1.2]\n",
      " [6.1 3.  4.6 1.4]\n",
      " [5.8 2.6 4.  1.2]\n",
      " [5.  2.3 3.3 1. ]\n",
      " [5.6 2.7 4.2 1.3]\n",
      " [5.7 3.  4.2 1.2]\n",
      " [5.7 2.9 4.2 1.3]\n",
      " [6.2 2.9 4.3 1.3]\n",
      " [5.1 2.5 3.  1.1]\n",
      " [5.7 2.8 4.1 1.3]\n",
      " [6.3 3.3 6.  2.5]\n",
      " [5.8 2.7 5.1 1.9]\n",
      " [7.1 3.  5.9 2.1]\n",
      " [6.3 2.9 5.6 1.8]\n",
      " [6.5 3.  5.8 2.2]\n",
      " [7.6 3.  6.6 2.1]\n",
      " [4.9 2.5 4.5 1.7]\n",
      " [7.3 2.9 6.3 1.8]\n",
      " [6.7 2.5 5.8 1.8]\n",
      " [7.2 3.6 6.1 2.5]\n",
      " [6.5 3.2 5.1 2. ]\n",
      " [6.4 2.7 5.3 1.9]\n",
      " [6.8 3.  5.5 2.1]\n",
      " [5.7 2.5 5.  2. ]\n",
      " [5.8 2.8 5.1 2.4]\n",
      " [6.4 3.2 5.3 2.3]\n",
      " [6.5 3.  5.5 1.8]\n",
      " [7.7 3.8 6.7 2.2]\n",
      " [7.7 2.6 6.9 2.3]\n",
      " [6.  2.2 5.  1.5]\n",
      " [6.9 3.2 5.7 2.3]\n",
      " [5.6 2.8 4.9 2. ]\n",
      " [7.7 2.8 6.7 2. ]\n",
      " [6.3 2.7 4.9 1.8]\n",
      " [6.7 3.3 5.7 2.1]\n",
      " [7.2 3.2 6.  1.8]\n",
      " [6.2 2.8 4.8 1.8]\n",
      " [6.1 3.  4.9 1.8]\n",
      " [6.4 2.8 5.6 2.1]\n",
      " [7.2 3.  5.8 1.6]\n",
      " [7.4 2.8 6.1 1.9]\n",
      " [7.9 3.8 6.4 2. ]\n",
      " [6.4 2.8 5.6 2.2]\n",
      " [6.3 2.8 5.1 1.5]\n",
      " [6.1 2.6 5.6 1.4]\n",
      " [7.7 3.  6.1 2.3]\n",
      " [6.3 3.4 5.6 2.4]\n",
      " [6.4 3.1 5.5 1.8]\n",
      " [6.  3.  4.8 1.8]\n",
      " [6.9 3.1 5.4 2.1]\n",
      " [6.7 3.1 5.6 2.4]\n",
      " [6.9 3.1 5.1 2.3]\n",
      " [5.8 2.7 5.1 1.9]\n",
      " [6.8 3.2 5.9 2.3]\n",
      " [6.7 3.3 5.7 2.5]\n",
      " [6.7 3.  5.2 2.3]\n",
      " [6.3 2.5 5.  1.9]\n",
      " [6.5 3.  5.2 2. ]\n",
      " [6.2 3.4 5.4 2.3]\n",
      " [5.9 3.  5.1 1.8]]\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.550847Z",
     "start_time": "2025-02-28T15:08:23.547543Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(lis.target_names)\n",
    "print(lis.target)"
   ],
   "id": "9cbab984918c4353",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['setosa' 'versicolor' 'virginica']\n",
      "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n",
      " 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2]\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.557186Z",
     "start_time": "2025-02-28T15:08:23.552211Z"
    }
   },
   "cell_type": "code",
   "source": "lis.DESCR",
   "id": "280b60c6d6d97bf4",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'.. _iris_dataset:\\n\\nIris plants dataset\\n--------------------\\n\\n**Data Set Characteristics:**\\n\\n:Number of Instances: 150 (50 in each of three classes)\\n:Number of Attributes: 4 numeric, predictive attributes and the class\\n:Attribute Information:\\n    - sepal length in cm\\n    - sepal width in cm\\n    - petal length in cm\\n    - petal width in cm\\n    - class:\\n            - Iris-Setosa\\n            - Iris-Versicolour\\n            - Iris-Virginica\\n\\n:Summary Statistics:\\n\\n============== ==== ==== ======= ===== ====================\\n                Min  Max   Mean    SD   Class Correlation\\n============== ==== ==== ======= ===== ====================\\nsepal length:   4.3  7.9   5.84   0.83    0.7826\\nsepal width:    2.0  4.4   3.05   0.43   -0.4194\\npetal length:   1.0  6.9   3.76   1.76    0.9490  (high!)\\npetal width:    0.1  2.5   1.20   0.76    0.9565  (high!)\\n============== ==== ==== ======= ===== ====================\\n\\n:Missing Attribute Values: None\\n:Class Distribution: 33.3% for each of 3 classes.\\n:Creator: R.A. Fisher\\n:Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)\\n:Date: July, 1988\\n\\nThe famous Iris database, first used by Sir R.A. Fisher. The dataset is taken\\nfrom Fisher\\'s paper. Note that it\\'s the same as in R, but not as in the UCI\\nMachine Learning Repository, which has two wrong data points.\\n\\nThis is perhaps the best known database to be found in the\\npattern recognition literature.  Fisher\\'s paper is a classic in the field and\\nis referenced frequently to this day.  (See Duda & Hart, for example.)  The\\ndata set contains 3 classes of 50 instances each, where each class refers to a\\ntype of iris plant.  One class is linearly separable from the other 2; the\\nlatter are NOT linearly separable from each other.\\n\\n.. dropdown:: References\\n\\n  - Fisher, R.A. \"The use of multiple measurements in taxonomic problems\"\\n    Annual Eugenics, 7, Part II, 179-188 (1936); also in \"Contributions to\\n    Mathematical Statistics\" (John Wiley, NY, 1950).\\n  - Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis.\\n    (Q327.D83) John Wiley & Sons.  ISBN 0-471-22361-1.  See page 218.\\n  - Dasarathy, B.V. (1980) \"Nosing Around the Neighborhood: A New System\\n    Structure and Classification Rule for Recognition in Partially Exposed\\n    Environments\".  IEEE Transactions on Pattern Analysis and Machine\\n    Intelligence, Vol. PAMI-2, No. 1, 67-71.\\n  - Gates, G.W. (1972) \"The Reduced Nearest Neighbor Rule\".  IEEE Transactions\\n    on Information Theory, May 1972, 431-433.\\n  - See also: 1988 MLC Proceedings, 54-64.  Cheeseman et al\"s AUTOCLASS II\\n    conceptual clustering system finds 3 classes in the data.\\n  - Many, many more ...\\n'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.573338Z",
     "start_time": "2025-02-28T15:08:23.569322Z"
    }
   },
   "cell_type": "code",
   "source": "x_train, x_test, y_train, y_test = train_test_split(lis.data, lis.target, test_size=0.25, random_state=1)",
   "id": "15e82694366c58b6",
   "outputs": [],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.589591Z",
     "start_time": "2025-02-28T15:08:23.586541Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(\"训练集特征值shape\", x_train.shape)\n",
    "print('-'*50)\n",
    "# print(\"测试集特征值和目标值：\", x_test, y_test)\n",
    "print(\"测试集特征值shape\", x_test.shape)"
   ],
   "id": "b5a189ba324a2eeb",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集特征值shape (112, 4)\n",
      "--------------------------------------------------\n",
      "测试集特征值shape (38, 4)\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.598486Z",
     "start_time": "2025-02-28T15:08:23.591492Z"
    }
   },
   "cell_type": "code",
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=3)\n",
    "knn.fit(x_train, y_train)\n",
    "y_predict = knn.predict(x_test)"
   ],
   "id": "c8fa19f6580699b6",
   "outputs": [],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.629269Z",
     "start_time": "2025-02-28T15:08:23.623235Z"
    }
   },
   "cell_type": "code",
   "source": "print(\"准确率：\",knn.score(x_test, y_test))",
   "id": "6b67212f680e2732",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率： 1.0\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:14:45.532145Z",
     "start_time": "2025-02-28T15:14:45.528373Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(y_predict)\n",
    "print(y_test)"
   ],
   "id": "54946513fac59c6e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 1 0 2 1 2 0 0 2 1 0 2 1 1 0 1 1 0 0 1 1 1 0 2 1 0 0 1 2 1 2 1 2 2 0 1\n",
      " 0]\n",
      "[0 1 1 0 2 1 2 0 0 2 1 0 2 1 1 0 1 1 0 0 1 1 1 0 2 1 0 0 1 2 1 2 1 2 2 0 1\n",
      " 0]\n"
     ]
    }
   ],
   "execution_count": 22
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.641658Z",
     "start_time": "2025-02-28T15:08:23.636774Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 假设 y_predict 是预测结果，ansdic 是类别名称的字典\n",
    "predicted_names = [lis.target_names[pred] for pred in y_predict]\n",
    "\n",
    "# 打印预测结果对应的类别名称\n",
    "for i, name in enumerate(predicted_names):\n",
    "    print(f\"样本 {i} 的预测类别是: {name}\")\n"
   ],
   "id": "1ab256b9b25c1dca",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "样本 0 的预测类别是: setosa\n",
      "样本 1 的预测类别是: versicolor\n",
      "样本 2 的预测类别是: versicolor\n",
      "样本 3 的预测类别是: setosa\n",
      "样本 4 的预测类别是: virginica\n",
      "样本 5 的预测类别是: versicolor\n",
      "样本 6 的预测类别是: virginica\n",
      "样本 7 的预测类别是: setosa\n",
      "样本 8 的预测类别是: setosa\n",
      "样本 9 的预测类别是: virginica\n",
      "样本 10 的预测类别是: versicolor\n",
      "样本 11 的预测类别是: setosa\n",
      "样本 12 的预测类别是: virginica\n",
      "样本 13 的预测类别是: versicolor\n",
      "样本 14 的预测类别是: versicolor\n",
      "样本 15 的预测类别是: setosa\n",
      "样本 16 的预测类别是: versicolor\n",
      "样本 17 的预测类别是: versicolor\n",
      "样本 18 的预测类别是: setosa\n",
      "样本 19 的预测类别是: setosa\n",
      "样本 20 的预测类别是: versicolor\n",
      "样本 21 的预测类别是: versicolor\n",
      "样本 22 的预测类别是: versicolor\n",
      "样本 23 的预测类别是: setosa\n",
      "样本 24 的预测类别是: virginica\n",
      "样本 25 的预测类别是: versicolor\n",
      "样本 26 的预测类别是: setosa\n",
      "样本 27 的预测类别是: setosa\n",
      "样本 28 的预测类别是: versicolor\n",
      "样本 29 的预测类别是: virginica\n",
      "样本 30 的预测类别是: versicolor\n",
      "样本 31 的预测类别是: virginica\n",
      "样本 32 的预测类别是: versicolor\n",
      "样本 33 的预测类别是: virginica\n",
      "样本 34 的预测类别是: virginica\n",
      "样本 35 的预测类别是: setosa\n",
      "样本 36 的预测类别是: versicolor\n",
      "样本 37 的预测类别是: setosa\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-28T15:08:23.771568Z",
     "start_time": "2025-02-28T15:08:23.642737Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def plot_decision_boundaries(X, y, model, ax, title=\"Decision Boundary\"):\n",
    "    h = .02  # Step size in the mesh\n",
    "    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1\n",
    "    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1\n",
    "    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),\n",
    "                         np.arange(y_min, y_max, h))\n",
    "\n",
    "    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])\n",
    "    Z = Z.reshape(xx.shape)\n",
    "    \n",
    "    # Create color maps\n",
    "    cmap_background = ListedColormap(['#FFAAAA', '#AAAAFF', '#AAFFAA'])\n",
    "    cmap_points = ListedColormap(['#FF0000', '#0000FF', '#00FF00'])\n",
    "    \n",
    "    ax.contourf(xx, yy, Z, alpha=0.3, cmap=cmap_background)\n",
    "    ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=cmap_points)\n",
    "    \n",
    "    ax.set_xlim(xx.min(), xx.max())\n",
    "    ax.set_ylim(yy.min(), yy.max())\n",
    "    ax.set_xticks(())\n",
    "    ax.set_yticks(())\n",
    "    ax.set_title(title)\n",
    "\n",
    "# Create figure and axes for the plot\n",
    "fig, ax = plt.subplots(figsize=(8, 6))\n",
    "\n",
    "# Plot decision boundary\n",
    "plot_decision_boundaries(X, lis.target_names, knn, ax)\n",
    "plt.show()"
   ],
   "id": "99b8898c75c9b522",
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'X' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[18], line 28\u001B[0m\n\u001B[0;32m     25\u001B[0m fig, ax \u001B[38;5;241m=\u001B[39m plt\u001B[38;5;241m.\u001B[39msubplots(figsize\u001B[38;5;241m=\u001B[39m(\u001B[38;5;241m8\u001B[39m, \u001B[38;5;241m6\u001B[39m))\n\u001B[0;32m     27\u001B[0m \u001B[38;5;66;03m# Plot decision boundary\u001B[39;00m\n\u001B[1;32m---> 28\u001B[0m plot_decision_boundaries(\u001B[43mX\u001B[49m, y, knn, ax)\n\u001B[0;32m     29\u001B[0m plt\u001B[38;5;241m.\u001B[39mshow()\n",
      "\u001B[1;31mNameError\u001B[0m: name 'X' is not defined"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 800x600 with 1 Axes>"
      ],
      "image/png": "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L7fXBisAAHzlUB09enRat25dmjJlSlq9enUaMGBAqqmpqXvAauXKlfWuoF533XWpXbt25a8ffPBB+ta3vlVG6q233lrpSwMA0IZUdI9qa7rnAQCAVnSPKgAANBehCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEDrCdXq6urUr1+/1KVLlzRkyJC0aNGiL91/w4YN6YorrkiHHnpo6ty5czrqqKPSvHnz9vWcAQBoAzpWesDs2bPThAkT0owZM8pInT59eqqqqkrLly9PPXr02G3/bdu2pR/+8Iflx5588snUp0+f9P7776eDDjqosb4GAABaoXZFURSVHJDj9JRTTkn33ntvub5jx47Ut2/fdOWVV6ZJkybttn8O2jvvvDMtW7Ys7bfffvt0kps2bUrdunVLGzduTF27dt2nzwEAQNNpil6r6K3/fHV08eLFacSIEf/9BO3bl+sLFy5s8JhnnnkmDR06tHzrv2fPnun4449Pt912W9q+ffseX2fr1q3lF7vzAgBA21JRqK5fv74MzBycO8vrq1evbvCYFStWlG/55+PyfanXX399uvvuu9Mtt9yyx9eZNm1aWeS1S75iCwBA29LkT/3nWwPy/akPPPBAGjhwYBo9enS69tpry1sC9mTy5MnlZePaZdWqVU19mgAAfJ0fpurevXvq0KFDWrNmTb3teb1Xr14NHpOf9M/3pubjah177LHlFdh8K0GnTp12OybPDJAXAADaroquqOaozFdF58+fX++KaV7P96E2ZNiwYentt98u96v11ltvlQHbUKQCAMA+vfWfp6aaOXNmevTRR9Obb76ZfvGLX6QtW7akcePGlR8fM2ZM+dZ9rfzxjz76KF111VVloM6dO7d8mCo/XAUAAI02j2q+x3TdunVpypQp5dv3AwYMSDU1NXUPWK1cubKcCaBWfhDqueeeS+PHj08nnnhiOY9qjtaJEydW+tIAALQhFc+j2hLMowoAEFuLz6MKAADNRagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAGg9oVpdXZ369euXunTpkoYMGZIWLVq0V8fNmjUrtWvXLo0aNWpfXhYAgDak4lCdPXt2mjBhQpo6dWpasmRJ6t+/f6qqqkpr16790uPee++99Otf/zoNHz78q5wvAABtRMWhes8996RLLrkkjRs3Lh133HFpxowZ6YADDkgPP/zwHo/Zvn17uuCCC9KNN96YDj/88K96zgAAtAEVheq2bdvS4sWL04gRI/77Cdq3L9cXLly4x+Nuuumm1KNHj3TRRRft1ets3bo1bdq0qd4CAEDbUlGorl+/vrw62rNnz3rb8/rq1asbPObll19ODz30UJo5c+Zev860adNSt27d6pa+fftWcpoAALQCTfrU/+bNm9OFF15YRmr37t33+rjJkyenjRs31i2rVq1qytMEACCgjpXsnGOzQ4cOac2aNfW25/VevXrttv8777xTPkQ1cuTIum07duz4/xfu2DEtX748HXHEEbsd17lz53IBAKDtquiKaqdOndLAgQPT/Pnz64VnXh86dOhu+x9zzDHp9ddfT0uXLq1bzj333HTmmWeWv/eWPgAAjXJFNctTU40dOzYNGjQoDR48OE2fPj1t2bKlnAUgGzNmTOrTp095n2meZ/X444+vd/xBBx1U/rrrdgAA+EqhOnr06LRu3bo0ZcqU8gGqAQMGpJqamroHrFauXFnOBAAAAF9Fu6IoihRcnp4qP/2fH6zq2rVrS58OAADN0GsufQIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFAKD1hGp1dXXq169f6tKlSxoyZEhatGjRHvedOXNmGj58eDr44IPLZcSIEV+6PwAA7FOozp49O02YMCFNnTo1LVmyJPXv3z9VVVWltWvXNrj/ggUL0nnnnZdefPHFtHDhwtS3b9901llnpQ8++MAIAACwR+2KoihSBfIV1FNOOSXde++95fqOHTvK+LzyyivTpEmT/ufx27dvL6+s5uPHjBmzV6+5adOm1K1bt7Rx48bUtWvXSk4XAIBm0BS9VtEV1W3btqXFixeXb9/XfYL27cv1fLV0b3zyySfp888/T4cccsge99m6dWv5xe68AADQtlQUquvXry+viPbs2bPe9ry+evXqvfocEydOTL17964Xu7uaNm1aWeS1S75iCwBA29KsT/3ffvvtadasWWnOnDnlg1h7Mnny5PKyce2yatWq5jxNAAAC6FjJzt27d08dOnRIa9asqbc9r/fq1etLj73rrrvKUH3hhRfSiSee+KX7du7cuVwAAGi7Krqi2qlTpzRw4MA0f/78um35Yaq8PnTo0D0ed8cdd6Sbb7451dTUpEGDBn21MwYAoE2o6IpqlqemGjt2bBmcgwcPTtOnT09btmxJ48aNKz+en+Tv06dPeZ9p9tvf/jZNmTIlPfbYY+Xcq7X3sn7jG98oFwAAaJRQHT16dFq3bl0Znzk6BwwYUF4prX3AauXKleVMALXuv//+craAH//4x/U+T56H9YYbbqj05QEAaCMqnke1JZhHFQAgthafRxUAAJqLUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAEBIQhUAgJCEKgAAIQlVAABCEqoAAIQkVAEACEmoAgAQklAFACAkoQoAQEhCFQCAkIQqAAAhCVUAAEISqgAAhCRUAQAISagCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIA0HpCtbq6OvXr1y916dIlDRkyJC1atOhL93/iiSfSMcccU+5/wgknpHnz5u3r+QIA0EZUHKqzZ89OEyZMSFOnTk1LlixJ/fv3T1VVVWnt2rUN7v/KK6+k8847L1100UXptddeS6NGjSqXN954ozHOHwCAVqpdURRFJQfkK6innHJKuvfee8v1HTt2pL59+6Yrr7wyTZo0abf9R48enbZs2ZKeffbZum2nnnpqGjBgQJoxY8ZeveamTZtSt27d0saNG1PXrl0rOV0AAJpBU/Rax0p23rZtW1q8eHGaPHly3bb27dunESNGpIULFzZ4TN6er8DuLF+Bffrpp/f4Olu3bi2XWvkLrv0/AACAeGo7rcJroI0XquvXr0/bt29PPXv2rLc9ry9btqzBY1avXt3g/nn7nkybNi3deOONu23PV24BAIjr3//+d3lltdlDtbnkK7Y7X4XdsGFD+s53vpNWrlzZaF84sb8jy9+UrFq1yq0ebYDxbluMd9tivNuWjRs3psMOOywdcsghjfY5KwrV7t27pw4dOqQ1a9bU257Xe/Xq1eAxeXsl+2edO3cul13lSPUfetuRx9p4tx3Gu20x3m2L8W5b2rdvvNlPK/pMnTp1SgMHDkzz58+v25YfpsrrQ4cObfCYvH3n/bPnn39+j/sDAMA+vfWf35IfO3ZsGjRoUBo8eHCaPn16+VT/uHHjyo+PGTMm9enTp7zPNLvqqqvSGWecke6+++50zjnnpFmzZqVXX301PfDAA0YAAIDGC9U83dS6devSlClTygei8jRTNTU1dQ9M5ftId77ke9ppp6XHHnssXXfddemaa65J3/ve98on/o8//vi9fs18G0Cet7Wh2wFofYx322K82xbj3bYY77alcxOMd8XzqAIAQHNovLtdAQCgEQlVAABCEqoAAIQkVAEACClMqFZXV6d+/fqlLl26pCFDhqRFixZ96f5PPPFEOuaYY8r9TzjhhDRv3rxmO1ead7xnzpyZhg8fng4++OByGTFixP/874NYKv3zXStPZ9euXbs0atSoJj9HWm68808fvOKKK9Khhx5aPi181FFH+Tu9FY93ntby6KOPTvvvv3/5U6vGjx+fPvvss2Y7X/bNSy+9lEaOHJl69+5d/r2cZ3D6XxYsWJBOPvnk8s/1kUcemR555JHKX7gIYNasWUWnTp2Khx9+uPjHP/5RXHLJJcVBBx1UrFmzpsH9//a3vxUdOnQo7rjjjuKf//xncd111xX77bdf8frrrzf7udP0433++ecX1dXVxWuvvVa8+eabxc9+9rOiW7duxb/+9a9mP3eafrxrvfvuu0WfPn2K4cOHFz/60Y+a7Xxp3vHeunVrMWjQoOLss88uXn755XLcFyxYUCxdurTZz52mH+8//vGPRefOnctf81g/99xzxaGHHlqMHz++2c+dysybN6+49tpri6eeeirPFlXMmTPnS/dfsWJFccABBxQTJkwoW+13v/td2W41NTUVvW6IUB08eHBxxRVX1K1v37696N27dzFt2rQG9//JT35SnHPOOfW2DRkypPj5z3/e5OdK84/3rr744oviwAMPLB599NEmPEtacrzzGJ922mnFgw8+WIwdO1aotuLxvv/++4vDDz+82LZtWzOeJS013nnfH/zgB/W25ZAZNmxYk58rjWdvQvXqq68uvv/979fbNnr06KKqqqqi12rxt/63bduWFi9eXL6dWyv/wIC8vnDhwgaPydt33j+rqqra4/7EsS/jvatPPvkkff755+mQQw5pwjOlJcf7pptuSj169EgXXXRRM50pLTXezzzzTPkjtfNb//kHx+QfBnPbbbel7du3N+OZ01zjnX8IUD6m9vaAFStWlLd5nH322c123jSPxmq1in8yVWNbv359+RdS7U+2qpXXly1b1uAx+SdiNbR/3k5s+zLeu5o4cWJ5j8yufwBoHeP98ssvp4ceeigtXbq0mc6SlhzvHCp//etf0wUXXFAGy9tvv50uv/zy8pvR/BNuaF3jff7555fHnX766fkd3fTFF1+kyy67rPzJlbQuq/fQaps2bUqffvppeY/y3mjxK6pQidtvv718wGbOnDnljfu0Lps3b04XXnhh+QBd9+7dW/p0aAY7duwor54/8MADaeDAgeWP6b722mvTjBkzWvrUaAL54Zp8xfy+++5LS5YsSU899VSaO3duuvnmm1v61Aiqxa+o5n+MOnTokNasWVNve17v1atXg8fk7ZXsTxz7Mt617rrrrjJUX3jhhXTiiSc28ZnSEuP9zjvvpPfee698snTnkMk6duyYli9fno444ohmOHOa6893ftJ/v/32K4+rdeyxx5ZXY/Jby506dWry86b5xvv6668vvxm9+OKLy/U8a8+WLVvSpZdeWn6Dkm8doHXotYdW69q1615fTc1a/L+I/JdQ/i56/vz59f5hyuv5vqWG5O077589//zze9yfOPZlvLM77rij/I67pqYmDRo0qJnOluYe7zzl3Ouvv16+7V+7nHvuuenMM88sf5+nsqF1/fkeNmxY+XZ/7Tck2VtvvVUGrEhtfeOdnzHYNUZrv0n5/2d0aC2GNlarFUGmt8jTVTzyyCPlFAaXXnppOb3F6tWry49feOGFxaRJk+pNT9WxY8firrvuKqcrmjp1qumpvkYqHe/bb7+9nP7kySefLD788MO6ZfPmzS34VdBU470rT/237vFeuXJlOYvHL3/5y2L58uXFs88+W/To0aO45ZZbWvCroKnGO/97ncf7T3/6Uzl90V/+8pfiiCOOKGfzIbbNmzeX00TmJefjPffcU/7+/fffLz+exzmP967TU/3mN78pWy1PM/m1nZ4qy/NrHXbYYWWQ5Oku/v73v9d97Iwzzij/sdrZ448/Xhx11FHl/nn6g7lz57bAWdMc4/2d73yn/EOx65L/wuProdI/3zsTqq1/vF955ZVyisEcPHmqqltvvbWcoozWN96ff/55ccMNN5Rx2qVLl6Jv377F5ZdfXvznP/9pobNnb7344osN/ltcO7751zzeux4zYMCA8r+N/Gf797//fVGpdvl/GvdiLwAAfHUtfo8qAAA0RKgCABCSUAUAICShCgBASEIVAICQhCoAACEJVQAAQhKqAACEJFQBAAhJqAIAEJJQBQAgJKEKAECK6P8AHBZ3ZezupBgAAAAASUVORK5CYII="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 18
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
